/*
	weak_type_value.cpp
	@author:Wolfhead
*/
#include "weak_type_value.h"
#include "weak_type_define.h"
#include "weak_type_holder.hpp"
#include "weak_type_allocator.hpp"
#include <sstream>

static wolv::weakType::Value _nullValue;
typedef wolv::weakType::allocator::Allocator<wolv::weakType::_detail::weakTypeHolder> holderAlloc;

#define CLONE_HOLDER() do\
{\
	if (holder_->Count() != 1) \
	{\
		_cloneHolder();\
	}\
} while (0)

std::string wolv::weakType::Value::TypeName( valueType type )
{
	switch (type)
	{
	case nullType : return "null";
	case intType : return "int";
	case boolType : return "bool";
	case doubleType : return "double";
	case stringType : return "string";
	case arrayType : return "array";
	case objectType : return "object";
	default : return "unknown";
	}
}


wolv::weakType::Value::Value()
{
	_createHolder();
	holder_->SetType(nullType);
}

wolv::weakType::Value::~Value()
{
	_releaseHolder();
}

wolv::weakType::Value::Value( wolv::weakType::valueType type /*= wolv::weakType::valueType::nullType*/ )
{
	_createHolder();
	holder_->SetType(type);
}

wolv::weakType::Value::Value(int value)
{
	_createHolder();
	holder_->SetInt(value);
}

wolv::weakType::Value::Value( bool value )
{
	_createHolder();
	holder_->SetBool(value);
}

wolv::weakType::Value::Value( double value )
{
	_createHolder();
	holder_->SetDouble(value);
}

wolv::weakType::Value::Value( const char* value )
{
	_createHolder();
	holder_->SetString(value);
}


wolv::weakType::Value& wolv::weakType::Value::operator=( const wolv::weakType::Value& value )
{
	if (this == &(value)) 
	{
		return *this;
	}

	_releaseHolder();
	holder_ = value.holder_;
	holder_->Ref();

	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::operator= (wolv::weakType::valueType type)
{
	CLONE_HOLDER();
	holder_->SetType(type);

	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::operator=( int value )
{
	CLONE_HOLDER();
	holder_->SetInt(value);

	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::operator=( bool value )
{
	CLONE_HOLDER();
	holder_->SetBool(value);

	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::operator=( double value )
{
	CLONE_HOLDER();
	holder_->SetDouble(value);

	return *this;
}



wolv::weakType::Value& wolv::weakType::Value::operator=( const char* value )
{
	CLONE_HOLDER();
	holder_->SetString(value);

	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::operator=( const std::string& value )
{
	CLONE_HOLDER();
	holder_->SetString(value);

	return *this;
}


// copy constructor copy the holder pointer and add ref-count
wolv::weakType::Value::Value( const Value& value )
{
	holder_ = value.holder_;
	holder_->Ref();
}


void wolv::weakType::Value::_createHolder()
{
	holder_ =  holderAlloc::alloc();
	holder_->Ref();
}

// to implement a copy on write schemer
void wolv::weakType::Value::_cloneHolder()
{
	HolderPtr tmp = holderAlloc::alloc(*holder_);

	holder_->Release();
	if (!holder_->Count()) 
	{
		holderAlloc::release(holder_);
	}
	holder_ = tmp;
	holder_->Ref();
}


void wolv::weakType::Value::_releaseHolder()
{
	holder_->Release();
	if (!holder_->Count()) 
	{
		holderAlloc::release(holder_);
	}
	holder_ = 0;
}

const wolv::weakType::Value& wolv::weakType::Value::operator[]( unsigned int index ) const
{
	if (holder_->GetArray().size() >= index + 1)
	{
		return holder_->GetArray()[index];
	}
	return _nullValue;
}

const wolv::weakType::Value& wolv::weakType::Value::operator[]( const char* key ) const
{
	object_type::const_iterator it;
	if ((it = holder_->GetObject().find(key)) != holder_->GetObject().end()) 
	{
		return it->second;
	}
	return _nullValue;
}

const wolv::weakType::Value& wolv::weakType::Value::operator[]( const std::string& key ) const
{
	object_type::const_iterator it;
	if ((it = holder_->GetObject().find(key)) != holder_->GetObject().end()) {
		return it->second;
	}
	return _nullValue;
}

wolv::weakType::Value& wolv::weakType::Value::operator[]( unsigned int index )
{
	CLONE_HOLDER();
	holder_->SetType(arrayType);
	return holder_->GetArray()[index];
}



wolv::weakType::Value& wolv::weakType::Value::operator[]( const char* key )
{
	CLONE_HOLDER();
	holder_->SetType(objectType);
	return holder_->GetObject()[key];
}



wolv::weakType::Value& wolv::weakType::Value::operator[]( const std::string& key )
{
	CLONE_HOLDER();
	holder_->SetType(objectType);
	return holder_->GetObject()[key];
}

bool wolv::weakType::Value::operator==( const Value& value )
{
	return *(this->holder_) == *value.holder_;
}

bool wolv::weakType::Value::operator!=( const Value& value )
{
	return !(*this == value);
}

bool wolv::weakType::Value::operator>( const Value& value )
{
	return *(this->holder_) > *value.holder_;
}

bool wolv::weakType::Value::operator<( const Value& value )
{
	return *(this->holder_) < *value.holder_;
}

bool wolv::weakType::Value::operator>=( const Value& value )
{
	return *(this->holder_) >= *value.holder_;
}

bool wolv::weakType::Value::operator<=( const Value& value )
{
	return *(this->holder_) <= *value.holder_;
}

bool wolv::weakType::Value::in( const Value& value )
{
	if (value.GetType() == objectType)
	{
		return (*this >= value[REGION_OPERATION_START])
			&& (*this <= value[REGION_OPERATION_END]);
	}
	else if (value.GetType() == arrayType)
	{
		for (array_type::iterator it = value.holder_->GetArray().begin();
			it != value.holder_->GetArray().end();
			++it
			)
		{
			if (*this == *it)
			{
				return true;
			}
		}

		return false;
	}
	else
	{
		return false;
	}

}

wolv::weakType::valueType wolv::weakType::Value::GetType() const
{
	return holder_->GetType();
}

void wolv::weakType::Value::setType(wolv::weakType::valueType type)
{
	CLONE_HOLDER();
	holder_->SetType(type);
}

wolv::weakType::Value& wolv::weakType::Value::append( const wolv::weakType::Value& value )
{
	CLONE_HOLDER();
	holder_->SetType(arrayType);
	holder_->GetArray().push_back(value);
	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::append( const char* key, const wolv::weakType::Value& value )
{
	CLONE_HOLDER();
	holder_->SetType(objectType);
	holder_->GetObject().insert(std::make_pair(key, value));
	return *this;
}

wolv::weakType::Value& wolv::weakType::Value::append( std::string key, const wolv::weakType::Value& value )
{
	CLONE_HOLDER();
	holder_->SetType(objectType);
	holder_->GetObject().insert(std::make_pair(key, value));
	return *this;
}

int wolv::weakType::Value::asInt() const
{
	return holder_->toInt();
}

double wolv::weakType::Value::asDouble() const
{
	return holder_->toDouble();
}

bool wolv::weakType::Value::asBool() const
{
	return holder_->toBool();
}

std::string wolv::weakType::Value::asString() const
{
	if (holder_->GetType() != arrayType && holder_->GetType() != objectType)
	{
		return holder_->toString();
	}
	else if (holder_->GetType() == arrayType)
	{
		std::ostringstream oos;
		oos << "(";
		for (
			array_type::iterator it = holder_->GetArray().begin(); 
			it != holder_->GetArray().end();
			++it
			)
		{
			oos << it->asString();
			if (it != holder_->GetArray().end() - 1)
			{
				oos << ",";
			}
		}
		oos << ")";
		return oos.str();
	}
	else if (holder_->GetType() == objectType)
	{
		std::ostringstream oos;
		oos << "{";
		for (
			object_type::iterator it = holder_->GetObject().begin(); 
			it != holder_->GetObject().end();
		++it
			)
		{
			oos << it->first << ":" <<  it->second.asString();
			object_type::iterator tmpIt = it; 
			if (++tmpIt != holder_->GetObject().end())
			{
				oos << ",";
			}
		}
		oos << "}";
		return oos.str();
	}
    return "unknown type";
}

wolv::weakType::valueType wolv::weakType::Value::TypeSuggest() const
{
	return holder_->typeSuggest();
}

int wolv::weakType::Value::StringTypeConvert()
{
	if (GetType() == stringType)
	{
		switch (TypeSuggest())
		{
		case intType:
			*this = asInt();
			break;
		case doubleType:
			*this = asDouble();
			break;
		case boolType:
			*this = asBool();
			break;
		default:
			//do nothing
			break;
		}
	}
	return 0;
}

void wolv::weakType::Value::_preRead()
{
	return;
}

void wolv::weakType::Value::_preWrite()
{
	return;
}

